home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * Copyright (c) 1990, 1991 Stanford University * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the name * Stanford may not be used in any advertising or publicity relating to * the software without the specific, prior written permission of * Stanford. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* $Header: /Source/Media/collab/TimeLine/RCS/instrument.c,v 1.2 91/10/03 17:39:01 chua Exp Locker: drapeau $ */ /* $Log: instrument.c,v $ * Revision 1.2 91/10/03 17:39:01 chua * In DrawNote, change the parameters to DrawBox. This is to correct an * error where if the zoom level is high, notes do not get drawn and * erased properly. * * Revision 1.1 91/09/30 22:38:54 chua * Removed a printf statement. * * Revision 1.0 91/09/30 16:57:54 chua * In InstrumentNew, instead of just assigning instrument->port to port, copy each entry * manually. * * Revision 0.71 91/09/26 18:01:15 chua * In FreeInstrument, free the instrument->port. * * Revision 0.70 91/09/25 14:05:02 chua * Changed InitInstInfoWindow to InitEditInfoWindow. * * Revision 0.69 91/09/25 13:49:14 chua * Changed the instrument field, instInfo, to editInfo. * Changed InstrumentInfo to EditInfo. * * Revision 0.68 91/09/20 11:40:27 chua * * Removed braces at line 273. * * Revision 0.67 91/09/19 17:28:49 chua * Make sure that variables are initialized properly. Change formatting slightly, * so that (if, for, while) statements with only one statement in them will not have * braces. * * Revision 0.66 91/09/17 17:16:23 chua * In InstrumentNew, correct some errors (line 275, 279) where it should be * instrument->port instead of just port. * * Revision 0.65 91/09/16 15:00:00 chua * In InstrumentNew, add a new parameter, appName, which indicates the name of the * application for this instrument. This parameter is used when the application is not * open, since there won't be a port number then. * * Also, in InstrumentNew, initialize the port structure and allocate memory for it. * * Added a new function, AddInstrument, which takes a port and tlFrame as parameters, and * adds the instrument to the instrument list. * * Revision 0.64 91/08/27 18:17:36 chua * In FreeInstrumentList, before doing a DestroySender, check that the * application is still alive. * * Revision 0.63 91/08/21 16:53:47 chua * In the InstrumentNew routine, the call to OpenAppsFindIcon now takes the instrument * as the parameter, instead of just the port. * * Revision 0.62 91/08/19 19:18:28 chua * In FreeInstrumentList, do a DestroySender. * * Revision 0.61 91/08/16 16:59:42 chua * In InstrumentNew, initialize the new variable, icon, which points to the pixmap * image of the icon for the application. * * In InstrumentDrawIcon, introduce a new type, Waiting, which will draw a red * background for the icon image. * * Revision 0.60 91/08/09 15:13:19 chua * In FindInstrument, if relativePosition is a negative number, return NULL. * * Revision 0.59 91/08/08 14:25:11 chua * In the InstrumentNew procedure, before creating a new sender, check that the application * does exist. * * Revision 0.58 91/07/22 15:16:58 chua * Added a new procedure, DrawPauseMarkers, to draw the pause markers. This procedure is called * by InstrumentDraw, and the markers are drawn just before the notes are drawn. * * Revision 0.57 91/07/18 15:05:47 chua * *** empty log message *** * * Revision 0.56 91/07/17 10:20:10 chua * In the DrawNote routine, set x to take into account the fact that the starting * position of the canvas may not be at time 0 but at some arbitrary time. * * In the InstrumentDrawNotes function, draw the note only if it is within the current * canvas area (which only covers a portion of the whole TimeLine document). * * In the InstrumentDrawCable function, take out the lines which draws the anchors, * as these are no longer in the canvas display. * * In the DrawTimeLine function, initialize the sec value with respect to the actual * start time corresponding to the start of the canvas. * * Revision 0.55 91/06/25 17:28:36 chua * Replaced occurrences of the constant HalfSecondScale by the value 5, as the constant is no longer * used. * In the DrawNote routine, scale x and the width according to the zoom level so that the note is placed * in the correct position on the canvas. * In the DrawTimeLine routine, use a different algorithm for calculating the time labels for the * time intervals. * In the InstrumentDrawNotes routine, check if a note is selected. If it is, draw it sunken. If not, * draw it raised. * * Revision 0.54 91/06/04 17:37:16 chua * Added the copyright comments in the beginning of the file. * * Revision 0.53 91/06/03 11:11:52 chua * Make changes to accomodate multiple documents. This involves identifying * which is the current active window, that is, the one where the last mouse * click was done. * * Revision 0.52 91/05/29 14:33:51 chua * Replace lines 311-314 in the InstrumentDrawIcon routine with a call to InstrumentMute, which * checks if the instrument mute indicator is to be drawn over the application icon for that * instrument. * * Revision 0.51 91/05/28 12:09:58 chua * In the InstrumentDrawIcon procedure, check if mute is set to ON for that instrument. If so, call the * InstrumentMuteOn routine to draw the mute indicator (the word "MUTE") besides the icon for that * instrument. * * Revision 0.50 91/05/24 16:36:41 chua * *** empty log message *** * * Revision 0.49 91/05/23 17:38:57 chua * *** empty log message *** * * Revision 0.48 91/05/22 16:40:08 chua * * * Revision 0.47 91/05/22 13:56:01 chua * * * Revision 0.46 91/05/22 11:40:55 chua * * * Revision 0.45 91/05/17 16:57:51 chua * *** empty log message *** * * Revision 0.44 91/05/17 16:56:56 chua * *** empty log message *** * * Revision 0.43 91/05/17 16:52:17 chua * *** empty log message *** * * Revision 0.42 1991/04/24 00:59:11 chua * Some minor changes in the parameters when calling the DrawBox routine from inside the * DrawNote function. The width is reduced by 1, as it turns out the original was inaccurate. * * A new function, FreeInstrumentList is added. It takes an instrument list head pointer as * an argument and frees all the nodes in the list, including all the notes lists. * * Revision 0.41 1991/04/08 20:59:33 chua * The DrawNote function is changed to accept a new parameter, 'type', which indicates if the note is to be * drawn 'Raised' or 'Sunken'. This is achieved by having a different foreground color (lighter for 'Raised' * and darker for 'Sunken') and having the borders drawn differently (refer to DrawBox routine). * Also, two additional fields are added to the instrument data structure. * infoNote points to the note structure that is currently selected in the info panel list. * selectedInfoNote gives the relative position of this selected note in the notes list of an instrument. * * The name of the function InstrumentDrawTimeLine is changed to DrawTimeLine, since this function is used * just once for the TimeLine application and not once for each instrument. * * Revision 0.40 1991/04/01 01:56:33 chua * This file contains functions for drawing most of the objects in the TimeLine Editor, and also functions * to create a new instrument node and find an instrument node. The functions are: * InstrumentNew - create a new instrument node and initialize the values. * FindInstrument - return a pointer to an instrument node given its relative position in the instrument list. * DrawBox - draws a border rectangle around a box. * DrawNote - this draws a rectangle which represents a note on the TimeLine. * InstrumentDrawNotes - draws all the notes belonging to an instrument. * InstrumentDrawCable - draws the cable belonging to an instrument. * DrawTimeLine - draws the timeline (on the TimeCanvas) with the time markings on it. * InstrumentDrawIcon - draws the icon for an instrument on the AppCanvas. * InstrumentDraw - draws the cable and notes for an instrument (by calling the two functions above * (InstrumentDrawNotes and InstrumentDrawCable). * */ static char instrumentrcsid[] = "$Header: /Source/Media/collab/TimeLine/RCS/instrument.c,v 1.2 91/10/03 17:39:01 chua Exp Locker: drapeau $"; #include "main.h" /* * This function draws the border for a box. The arguments passed in are the display and drawable of the canvas to be drawn in, * the coordinates for the top-left and bottom-right corners of the box, and a type which indicates if the box should be drawn 'raised' or * 'sunken'. * 'Raised' means the top and left borders are drawn in white, and the other two in black, giving the box a 3-D raised look. * 'Sunken' means the top and left borders are drawn in black, and the other two in white, giving the box a 3-D sunken look. * If type is 'Waiting', it is treated the same way as 'Sunken'. * Called by DrawNote and InstrumentDrawIcon (instrument.c) */ void DrawBox(dpy, xid, x1, y1, x2, y2, type, tlFrame) Display *dpy; Drawable xid; int x1, y1, x2, y2, type; TimeLineFramePtr tlFrame; { XPoint *points = (XPoint*) malloc (sizeof (XPoint) *3); /* Array of point coordinates to be passed to the XDrawLines routine */ if (type == Raised) /* Draw the top and left borders first */ XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[White]); else XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[Black]); points[0].x = x1; points[0].y = y2; points[1].x = x1; points[1].y = y1; points[2].x = x2; points[2].y = y1; XDrawLines(dpy, xid, tlFrame->gc, points, 3, CoordModeOrigin); if (type == Raised) /* Now draw the right and bottom borders */ XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[Black]); else XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[White]); points[0].x = x2; points[0].y = y1; points[1].x = x2; points[1].y = y2; points[2].x = x1; points[2].y = y2; XDrawLines(dpy, xid, tlFrame->gc, points, 3, CoordModeOrigin); } /* * Routine to draw a note. Currently just draws a note in the raised mode. * First, the foreground color is set to Grey92, then the rectangle representing the note is drawn. * The DrawBox function is then called to draw the border, given it the 'raised' look. * x, y are the coordinates for the top left corner of the note, and width is the length of the note. * type indicates if the note should be Raised or Sunken. * Called by InstrumentDrawNotes (instrument.c) and AddandDisplayNewNote (note.c) */ DrawNote(x, y, width, type, tlFrame) int x, y, width, type; TimeLineFramePtr tlFrame; { int drawWidth; int newX; newX = (x / tlFrame->zoomLevel) - tlFrame->canvasStart; /* Draw the note on the proper position in the canvas, depending on the */ drawWidth = width / tlFrame->zoomLevel; /* zoom level */ if (drawWidth < 2) drawWidth = 2; if (type == Raised) /* Check if note should be Raised or Sunken */ XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Grey92]); /* and set the foreground color accordingly */ else XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Grey65]); XFillRectangle(tlFrame->dpyDraw, tlFrame->xidDraw, tlFrame->gc, newX, y, drawWidth, NoteHeight); /* Draw the note */ DrawBox(tlFrame->dpyDraw, tlFrame->xidDraw, newX + 1, y+1, newX+drawWidth, y+NoteHeight-2, type, tlFrame); /* Draw the border */ } /* * This function will create a new instrument node (please refer to the header for instrument.h for a description of the instrument and note data * structures). It takes as arguments the relative position of the instrument in the instrument list (in the order registered with the Port Manager), and * the port number of the application that this instrument represents. It then initializes the fields of the instrument data structure. Again, please * refer to instrument.h for a description of what each field represents. * Called by OpenAppsInitialize (openApps.c) */ Instrument* InstrumentNew (relativePosition, port, tlFrame, appName) int relativePosition; Port *port; TimeLineFramePtr tlFrame; char *appName; { Instrument *instrument = (Instrument *) malloc (sizeof (Instrument)); instrument->relativePosition = relativePosition; instrument->cableStart = (IconHeight + IconGap) * relativePosition + FirstCableYPosition; instrument->port = (Port *) malloc(sizeof(Port)); instrument->port->appName = (char *) malloc (MAXPATHLEN); instrument->port->hostName = (char *) malloc (MAXPATHLEN); instrument->port->portNumber = -1; if (port == NULL) { strcpy(instrument->port->appName, appName); strcpy(instrument->port->hostName, "App not open"); } else { instrument->port->portNumber = port->portNumber; strcpy(instrument->port->hostName, port->hostName); strcpy(instrument->port->appName, port->appName); } if (strcmp(instrument->port->hostName, "App not open") != 0) instrument->sender = NewSender(port); instrument->icon = (Pixmap) xv_get(OpenAppsFindIcon(instrument), /* Get the pixmap image of the icon */ SERVER_IMAGE_PIXMAP); instrument->numnotes = 0; instrument->playNote = 0; instrument->partialNote = 0; instrument->firstNote = NULL; instrument->infoNote = NULL; instrument->currentNote = NULL; instrument->selectedInfoNote = -1; instrument->editInfo = NULL; instrument->next = NULL; InitEditInfoWindow(instrument, tlFrame); /* Create the info popup window */ return instrument; } /* * This function will add a new instrument to the instrument list. */ void AddInstrument(port, tlFrame) Port *port; TimeLineFramePtr tlFrame; { Instrument *lastInstrument; /* Current last instrument in the list */ if (tlFrame->numberOfApps == 0) /* First application to be added */ tlFrame->instHead = (Instrument *) InstrumentNew(0, port, tlFrame, NULL); else /* Add this application on to the application list */ { lastInstrument = (Instrument *) FindInstrument(tlFrame->numberOfApps - 1, tlFrame); lastInstrument->next = (Instrument *) InstrumentNew(tlFrame->numberOfApps, port, tlFrame, NULL); } tlFrame->numberOfApps++; /* Increment the number of open apps counter */ } /* * Function that will take a head pointer to an instrument list and frees all the instruments and their note lists. * Called by CopyToClipboard (select.c), UpdateAppsHandler (openApps.c) */ void FreeInstrumentList(tlFrame) TimeLineFramePtr tlFrame; { Instrument *instrument, *ifree; Sender *sender; ClearAllNotes(tlFrame); instrument = tlFrame->instHead; while (instrument != NULL) { ifree = instrument; xv_destroy_safe(instrument->editInfo->EditInfoWindow); if (strcmp(instrument->port->hostName, "App not open") != 0) { sender = NewSender(instrument->port); if (sender != NULL) { DestroySender(instrument->sender); DestroySender(sender); } free(instrument->port); } instrument = instrument->next; free (ifree); } tlFrame->instHead = (Instrument *) NULL; tlFrame->numberOfApps = 0; tlFrame->selectedInstrument = (Instrument *) NULL; tlFrame->noteInstrument = (Instrument *) NULL; } /* * Function that will return a pointer to the appropriate instrument node given its relative position in the instrument list. * Called by DrawCanvasEventHandler and AppCanvasEventHandler (canvas.c). */ Instrument *FindInstrument(relativePosition, tlFrame) int relativePosition; TimeLineFramePtr tlFrame; { int i; Instrument* currentInst; if (relativePosition < 0) { return NULL; } currentInst = tlFrame->instHead; /* To find the appropriate instrument node */ for (i=0; i < relativePosition && currentInst != NULL; i++) currentInst = currentInst->next; return currentInst; } /* * This function draws all the notes for a given instrument. It goes down the notes list in the instrument data structure and * calls the DrawNote routine to draw each note. * Called by InstrumentDraw (instrument.c) */ void InstrumentDrawNotes(instrument, tlFrame) Instrument *instrument; TimeLineFramePtr tlFrame; { Note *note; int canvasStart; int TimeLineLength; int type; canvasStart = tlFrame->canvasStart * tlFrame->zoomLevel; TimeLineLength = tlFrame->TimeLineLength * tlFrame->zoomLevel; for (note = instrument->firstNote; note != NULL; note = note->next) { if ((note->start >= canvasStart && note->start <= canvasStart + TimeLineLength) || (note->end >= canvasStart && note->end <= canvasStart + TimeLineLength)) { type = Raised; if (note == instrument->infoNote) type = Sunken; DrawNote(note->start, instrument->cableStart - NoteHeight/2, note->end - note->start, type, tlFrame); } } } /* * Draw the instrument cable and its ends (anchors). * Called by InstrumentDraw (instrument.c) */ void InstrumentDrawCable(instrument, tlFrame) Instrument *instrument; TimeLineFramePtr tlFrame; { XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Black]); /* Set to draw in black */ XFillRectangle(tlFrame->dpyDraw,tlFrame->xidDraw,tlFrame->gc, 0, /* Draw the cable */ instrument->cableStart - CableHeight/2, tlFrame->TimeLineLength, CableHeight); } /* * Draws the pause markers. */ void DrawPauseMarkers(tlFrame) TimeLineFramePtr tlFrame; { Pause *pause; int canvasStart; int TimeLineLength; int startPosition; canvasStart = tlFrame->canvasStart * tlFrame->zoomLevel; TimeLineLength = tlFrame->TimeLineLength * tlFrame->zoomLevel; XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Red]); for (pause = tlFrame->pauseHead; pause != NULL; pause = pause->next) { if (pause->position >= canvasStart && pause->position <= canvasStart + TimeLineLength) { startPosition = (pause->position / tlFrame->zoomLevel) - tlFrame->canvasStart; XDrawLine(tlFrame->dpyDraw, tlFrame->xidDraw, tlFrame->gc, startPosition, 0, startPosition, tlFrame->numberOfApps * 72 + FirstCableYPosition); } } } /* * This function draws the timeline with the time labels in intervals depending on the zoom level. * Called by TimeCanvasRepaintHandler (canvas.c) */ void DrawTimeLine(tlFrame) TimeLineFramePtr tlFrame; { long i, min, sec; char msg[10]; XSetForeground(tlFrame->dpyTime, tlFrame->gc, (long)tlFrame->pixelTable[Black]); /* Set the foreground color to black */ XFillRectangle(tlFrame->dpyTime,tlFrame->xidTime,tlFrame->gc, /* Draw the cable */ 0, TimeLineY - 1, tlFrame->TimeLineLength, 2); for (i=0; i < tlFrame->TimeLineLength; i += PixelsPerSecond * TimeLineInterval) /* Draw the time markers */ XFillRectangle(tlFrame->dpyTime, tlFrame->xidTime, tlFrame->gc, i, TimeLineY - (MarkerHeight/2), MarkerWidth, MarkerHeight); min = 0; /* Display the time intervals */ sec = tlFrame->canvasStart * tlFrame->zoomLevel / PixelsPerSecond; for (i=32; i < tlFrame->TimeLineLength; i += PixelsPerSecond * TimeLineInterval) { /* The number 32 is obtained by trial and error. It is the starting x coodinate */ /* of the first time interval */ sec += TimeLineInterval * tlFrame->zoomLevel; /* Update the time */ while (sec >= 60) { sec -= 60; min ++; } sprintf (msg, "%02d:%02d", min, sec); XDrawString(tlFrame->dpyTime, tlFrame->xidTime, tlFrame->gc, i, TimeLineY + 17, msg, 5); } } /* * This function will draw the icon bitmap of an instrument on the AppCanvas. * It takes as arguments a pointer to the instrument note, and a type which indicates if the icon is to be drawn in the raised or sunken mode, or * in wait state (background red). * First, the OpenAppsFindIcon function is called to get the bitmap image of the icon. * After setting the appropriate background color depending on the drawing mode (raised or sunken), the XCopyPlane Xlib routine is called which * copies the bitmap onto the canvas. * The DrawBox routine is then called to draw the borders, giving the icon the raised or sunken look. * Finally, the InstrumentMute procedure is called to see if the mute symbol is to be drawn across the application icon. * Called by AppCanvasEventHandler and AppCanvasRepaintHandler (canvas.c) */ void InstrumentDrawIcon(instrument, type, tlFrame) Instrument *instrument; int type; TimeLineFramePtr tlFrame; { XSetForeground(tlFrame->dpyApp, tlFrame->gc, (long)tlFrame->pixelTable[Black]); /* Set the foreground color to black */ if (type == Raised) /* Set the background color to either Grey92 (a lighter grey) or */ XSetBackground(tlFrame->dpyApp, tlFrame->gc, /* Grey65 (a darker grey) depending on whether the icon is to be */ (long)tlFrame->pixelTable[Grey92]); /* drawn raised or sunken */ else if (type == Sunken) XSetBackground(tlFrame->dpyApp, tlFrame->gc, (long)tlFrame->pixelTable[Grey65]); else XSetBackground(tlFrame->dpyApp, tlFrame->gc, (long)tlFrame->pixelTable[Red]); XCopyPlane(tlFrame->dpyApp, instrument->icon, tlFrame->xidApp, tlFrame->gc, /* Copy the 1-bit deep icon into the 8-bit deep canvaswindow */ 0, 0, IconHeight, IconHeight, IconXOffset, instrument->cableStart - IconHeight/2, 1); DrawBox(tlFrame->dpyApp, tlFrame->xidApp, IconXOffset, /* Draw the borders for the icon */ instrument->cableStart - 32, IconXOffset + IconHeight, instrument->cableStart + IconHeight/2, type, tlFrame); InstrumentMute (instrument, tlFrame); } /* * Draw the instrument cable and notes for the specified instrument. * Called by DrawCanvasRepaintHandler (canvas.c) */ void InstrumentDraw(instrument, tlFrame) Instrument *instrument; TimeLineFramePtr tlFrame; { InstrumentDrawCable(instrument, tlFrame); DrawPauseMarkers(tlFrame); InstrumentDrawNotes(instrument, tlFrame); }